/*
 * xPL.Arduino v0.1, xPL Implementation for Arduino
 *
 * This code is parsing a xPL message stored in 'received' buffer
 * - isolate and store in 'line' buffer each part of the message -> detection of EOL character (DEC 10)
 * - analyse 'line', function of its number and store information in xpl_header memory
 * - check for each step if the message respect xPL protocol
 * - parse each command line
 *
 * Copyright (C) 2012 johan@pirlouit.ch, olivier.lebrun@gmail.com
 * Original version by Gromain59@gmail.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include <xPL.h>
#include <EtherCard.h>

byte Ethernet::buffer[XPL_MESSAGE_BUFFER_MAX];
xPL xpl;

// Init du serveur HTTP
uint8_t mymac[6] = { 0x54,0x55,0x58,0x10,0x00,0x11 };
uint8_t myip[4] = { 192,168,0,133 };
uint8_t gwip[4] = { 192,168,0,240};

// Ethercard seems to only send broadcast on this addr
// find using xpl-perl, don't forget to add "--define broadcast=0.0.0.0" to the xpl-hub
uint8_t broadcast[4] = { 255,255,255,255};
  
void SendUdPMessage(char *buffer, int len)
{
    ether.sendUdp (buffer, len, xpl.udp_port, broadcast, xpl.udp_port);
}

void AfterParseAction(xPL_Message * message)
{
	if (xpl.TargetIsMe(message))
    {
      if (message->IsSchema("lighting", "basic"))
      {
        Serial.println("is lighting.basic");  
      }
    }
    
    // show message     
    Serial.println(message->toString());
}

void setup()
{
  Serial.begin(115200);
      
  if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
  {
    Serial.println( "Failed to access Ethernet controller");
  }

  ether.staticSetup(myip, gwip);

  Serial.println("Ethernet controller ready"); 
  
  xpl.SendExternal = &SendUdPMessage;  // pointer to the send callback
  xpl.AfterParseAction = &AfterParseAction;  // pointer to a post parsing action callback 
  xpl.Begin("xpl", "arduino", "test"); // parameters for hearbeat message
  xpl.hbeat_interval = 5; // interval of heartbeat message
}

void loop()
{
   xpl.Process();  // heartbeat management
  
   word len = ether.packetReceive();
   if( len > 0 ) 
   {
     // Check if Xpl UDP packet
     if( isXpl( Ethernet::buffer ) )
     {
       char xPLMessageBuff[XPL_MESSAGE_BUFFER_MAX];
       ByteToChar(Ethernet::buffer, xPLMessageBuff, len);
   
       // parse du message
       xpl.ParseInputMessage(xPLMessageBuff); 
     }
   }
}

boolean isXpl( uint8_t *buffer)
{
  return ( buffer[IP_PROTO_P] == IP_PROTO_UDP_V
            && buffer[UDP_DST_PORT_L_P] == XPL_PORT_L
            && buffer[UDP_DST_PORT_H_P] == XPL_PORT_H);
}

// convert byte* to char*
void ByteToChar(byte* bytes, char* chars, unsigned int count)
{
    for(unsigned int j = 0, i = UDP_DATA_P; i < count; i++)
    {
    	chars[j++] = (char)bytes[i];
    }
}